package com.rem.elasticsearch.apidemo.doc;

import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.FuzzyQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;

import java.io.IOException;

import static org.apache.http.HttpHost.DEFAULT_SCHEME_NAME;

/**
 * 条件查询文档
 * 查询构造器：SearchRequest  -> SearchSourceBuilder
 * 条件构造器 QueryBuilders query 查询
 * *                      matchAllQuery   全查询
 * *                      termQuery       精准查询相当于equals
 * *                      from/size       分页查询
 * *                      sort            排序
 * *                      fetchSource     筛选过滤
 * *                      boolQuery       组合查询
 * *                      rangeQuery      范围查找
 * *                      fuzzyQuery      模糊查询
 * *                      highlighter  -> HighlightBuilder 高亮查询
 * 条件构造器 QueryBuilders aggregation 聚合
 * *        AggregationBuilders
 * *                      terms           分组
 * *                      max             最大值
 * *                      sum             求和
 * *                      count           统计
 * *                      ...
 *
 * @author Rem
 * @date 2021-05-30
 */

public class DocQuery {

    public static void main(String[] args) throws IOException {
        // 创建ES客户端
        RestHighLevelClient esClient = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, DEFAULT_SCHEME_NAME)));
        // 1. 查询索引中全部的数据
        //matchAll(esClient);
        //2. 条件查询 termQuery
        //termQuery(esClient);
        //3. 分页查询
        //page(esClient);
        // 4. 排序查询
        //sort(esClient);
        // 5.过滤字段
        //filter(esClient);
        //6. 组合查询
        //team(esClient);
        //范围查询
        //rangeQuery(esClient);
        // 8. 模糊查询
        //fuzzyQuery(esClient);
        // 9. 高亮查询
        // highlighter(esClient);
        // 10. 聚合查询
        //aggregation(esClient);
        //分组查询
        grouping(esClient);

        // 关闭ES客户端
        esClient.close();
    }

    private static void grouping(RestHighLevelClient esClient) throws IOException {
        SearchRequest request = new SearchRequest().indices("user");
        AggregationBuilder aggregationBuilder = AggregationBuilders.terms("ageGroup").field("age");
        request.source(SearchSourceBuilder.searchSource().aggregation(aggregationBuilder));
        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
        System.err.println(response);
        SearchHits hits = response.getHits();
        hits.forEach(h -> System.out.println("结果集：" + h.getSourceAsString()));
    }

    private static void aggregation(RestHighLevelClient esClient) throws IOException {
        SearchRequest request = new SearchRequest().indices("user");
        SearchSourceBuilder builder = SearchSourceBuilder.searchSource();
        builder.aggregation(AggregationBuilders.max("maxAge").field("age"));
        request.source(builder);
        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

        SearchHits hits = response.getHits();
        System.err.println(response);
        hits.forEach(h -> System.out.println("结果集：" + h.getSourceAsString()));
    }

    /**
     * 高亮查询
     *
     * @param esClient
     * @throws IOException
     */
    private static void highlighter(RestHighLevelClient esClient) throws IOException {
        SearchRequest request = new SearchRequest().indices("user");

        SearchSourceBuilder builder = SearchSourceBuilder.searchSource();
        builder.query(QueryBuilders.termsQuery("age", "30"));

        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<font color='red'>");
        highlightBuilder.postTags("</font>");
        highlightBuilder.field("name");
        builder.highlighter(highlightBuilder);

        request.source(builder);
        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
        System.err.println(response);
        SearchHits hits = response.getHits();
        hits.forEach(h -> System.out.println("结果集：" + h.getSourceAsString()));
    }

    /**
     * 模糊查询
     *
     * @param esClient
     * @throws IOException
     */
    private static void fuzzyQuery(RestHighLevelClient esClient) throws IOException {
        SearchRequest request = new SearchRequest().indices("user");
        FuzzyQueryBuilder builder = QueryBuilders.fuzzyQuery("name", "wangwu").fuzziness(Fuzziness.ONE);

        request.source(SearchSourceBuilder.searchSource().query(builder));

        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
        SearchHits hits = response.getHits();
        hits.forEach(h -> System.out.println("结果集：" + h.getSourceAsString()));
    }

    /**
     * 范围查询
     *
     * @param esClient
     * @throws IOException
     */
    private static void rangeQuery(RestHighLevelClient esClient) throws IOException {
        SearchRequest request = new SearchRequest().indices("user");

        RangeQueryBuilder builder = QueryBuilders.rangeQuery("age").gte(30).lt(50);
        request.source(SearchSourceBuilder.searchSource().query(builder));

        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
        SearchHits hits = response.getHits();
        hits.forEach(h -> System.out.println("结果集：" + h.getSourceAsString()));
    }

    /**
     * 组合查询
     *
     * @param esClient
     * @throws IOException
     */
    private static void team(RestHighLevelClient esClient) throws IOException {
        SearchRequest request = new SearchRequest("user");

        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        boolQuery.must(QueryBuilders.matchQuery("age", "60"));
        boolQuery.should(QueryBuilders.termQuery("age", "60"));
        boolQuery.should(QueryBuilders.termQuery("age", "50"));
        boolQuery.mustNot(QueryBuilders.matchQuery("sex", "女"));
        boolQuery.filter(QueryBuilders.termsQuery("name", "wangwu555"));

        request.source(SearchSourceBuilder.searchSource().query(boolQuery));
        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

        SearchHits hits = response.getHits();
        hits.forEach(h -> System.out.println("结果集：" + h.getSourceAsString()));
    }

    /**
     * 过滤字段
     *
     * @param esClient
     * @throws IOException
     */
    private static void filter(RestHighLevelClient esClient) throws IOException {
        SearchRequest request = new SearchRequest("user");
        String[] includes = {"name", "age"};
        String[] excludes = {"sex"};
        request.source(SearchSourceBuilder.searchSource().query(QueryBuilders.matchAllQuery()).fetchSource(includes, excludes));
        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

        SearchHits hits = response.getHits();
        hits.forEach(h -> System.out.println("结果集：" + h.getSourceAsString()));
    }

    /**
     * 排序查询
     *
     * @param esClient
     * @throws IOException
     */
    private static void sort(RestHighLevelClient esClient) throws IOException {
        SearchRequest request = new SearchRequest("user");
        request.source(SearchSourceBuilder.searchSource().query(QueryBuilders.matchAllQuery()).sort("age", SortOrder.DESC));
        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

        SearchHits hits = response.getHits();
        hits.forEach(h -> System.out.println("结果集：" + h.getSourceAsString()));
    }

    /**
     * 分页查询
     *
     * @param esClient
     * @throws IOException
     */
    private static void page(RestHighLevelClient esClient) throws IOException {
        SearchRequest request = new SearchRequest("user");
        request.source(SearchSourceBuilder.searchSource().query(QueryBuilders.matchAllQuery()).from(0).size(2));
        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

        SearchHits hits = response.getHits();
        hits.forEach(h -> System.out.println("结果集：" + h.getSourceAsString()));
    }

    /**
     * 条件查询  eq
     *
     * @param esClient
     * @throws IOException
     */
    private static void termQuery(RestHighLevelClient esClient) throws IOException {
        SearchRequest request = new SearchRequest("user");
        request.source(SearchSourceBuilder.searchSource().query(QueryBuilders.termQuery("age", 60)));
        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

        SearchHits hits = response.getHits();
        hits.forEach(h -> System.out.println("结果集：" + h.getSourceAsString()));
    }

    /**
     * 查询索引中全部的数据
     *
     * @param esClient
     * @throws IOException
     */
    private static void matchAll(RestHighLevelClient esClient) throws IOException {
        SearchRequest request = new SearchRequest();
        request.indices("user");

        //匹配所有
        request.source(SearchSourceBuilder.searchSource().query(QueryBuilders.matchAllQuery()));

        //返回结果
        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

        SearchHits hits = response.getHits();

        System.out.println("结果数:" + hits.getTotalHits());
        System.out.println("耗时：" + response.getTook());

        for (SearchHit hit : hits) {
            System.out.println("结果集：" + hit.getSourceAsString());
        }
        System.out.println("_result:" + response.toString());
    }
}
